package com.bitmain.mmst.miner.statistic;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.TimeZone;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.BooleanUtils;

import com.bitmain.mmst.domain.MineHashrateOverview;
import com.bitmain.mmst.domain.MinerDetectBatch;
import com.bitmain.mmst.domain.MinerDetectDetail;
import com.bitmain.mmst.domain.MinerShelf;
import com.bitmain.mmst.domain.MinerType;
import com.bitmain.mmst.domain.ShelfHashrateOverview;
import com.bitmain.mmst.feature.cache.GlobalDataBuffer;
import com.bitmain.mmst.feature.time.TimeService;
import com.bitmain.mmst.miner.monitor.helper.DetectDataHelper;
import com.bitmain.mmst.miner.statistic.helper.OverviewDataHelper;
import com.bitmain.ulnar.aider.DateAider;

/**
 * 
 *
 * @author Richard - rui.wu@bitmain.com
 * @since 2016年7月11日
 *
 */
public class MinerStatistician {

	public static void executeHashrateOverview(MinerDetectBatch batch) {
		int numAll = batch.getNumAll();
		int numDetect = batch.getNumDetect();
		int numDetail = batch.getNumDetail();
		int numFailure = batch.getNumFailure();
		long detectTime = batch.getDetectTime();
		
		int numPassed = 0;
		int numUnpassed = 0;
		double overallTheory = 0.0;
		double overallReal = 0.0;
		double ratePassed = 0.0;
		
		TimeZone timeZone = TimeService.getTimeZone();
		String pattern = "yyyy";
		String detectYear = DateAider.formatMillis(detectTime, timeZone, pattern);
		int year = Integer.parseInt(detectYear);
		String nextYear = String.valueOf(year+1);
		long yearBeginning = DateAider.parseMillis(detectYear, timeZone, pattern);
		long yearEnd = DateAider.parseMillis(nextYear, timeZone, pattern);
		
		boolean tableExists = OverviewDataHelper.shelfHashrateOverviewTableExists(year);
		if(BooleanUtils.isNotTrue(tableExists)){
			OverviewDataHelper.createShelfHashrateOverviewTable(year, yearBeginning, yearEnd);
			System.out.println("mms_shelf_hashrate_overview_"+year+"表创建成功");
		}else{
			System.out.println("mms_shelf_hashrate_overview_"+year+"表存在");
		}
				
		List<MinerShelf> shelfs = DetectDataHelper.fetchAllShelfs();
		
		if(CollectionUtils.isEmpty(shelfs)){
			return;
		}
		
		for(MinerShelf shelf:shelfs){
			long minerShelfId = shelf.getId();
			String minerShelfName = shelf.getName();
			
			int ignoreNum = 0;
			if(ArrayUtils.isNotEmpty(shelf.getIgnores())){
				ignoreNum = shelf.getIgnores().length;
			}
			int ipBeginning = shelf.getIpBeginning();
			int ipEnd = shelf.getIpEnd();
			if(ipEnd<ipBeginning){
				int temp = ipEnd;
				ipEnd = ipBeginning;
				ipBeginning = temp;
			}
			
			int shelfNumAll = ipEnd - ipBeginning -ignoreNum +1;  
			
			int shelfNumDetail = 0;
			int shelfNumFailure = 0;
			int shelfNumPassed = 0;
			int shelfNumUnpassed = 0;
			double shelfOverallTheo = 0.0;
			double shelfOverallReal = 0.0;
			double shelfRatePassed = 0.0;
			
			List<MinerDetectDetail> details = OverviewDataHelper.getDetectDetails(minerShelfId,detectTime);
			
			if(!CollectionUtils.isEmpty(details)){
				shelfNumDetail = details.size();
				shelfNumFailure = shelfNumAll - shelfNumDetail;
				for(MinerDetectDetail detail:details){
					String minerTypeName = detail.getMinerType();
					MinerType minerType = GlobalDataBuffer.getMinerType(minerTypeName);
					
					if(minerType==null){
						minerType = GlobalDataBuffer.getMinerType(minerShelfId);
					}
					double typeHashPassed = minerType.getHashPass();
					double typeHashTheo = minerType.getHashTheo();
					
//					double typeHashPassed = 9600.0;
//					double typeHashTheo = 13000.0;
					
					shelfOverallTheo += typeHashTheo;
					double detailHashReal = 0;
					if(detail.getHashReal()!=null){
						detailHashReal = detail.getHashReal();
					}
					
					shelfOverallReal += detailHashReal;
					
					if(detailHashReal >= typeHashPassed){
						shelfNumPassed ++;
					}else{
						shelfNumUnpassed ++;
					}
				}
			}else{
				shelfNumDetail = 0;
				shelfNumFailure = shelfNumAll;
				shelfNumPassed = 0 ;
				shelfNumUnpassed = 0;
			}
			if(shelfNumDetail == 0){
				shelfRatePassed = 0;
			}else{
				shelfRatePassed = new BigDecimal((double) shelfNumPassed / (double) shelfNumDetail).setScale(4, RoundingMode.HALF_UP).doubleValue();
			}
			
			ShelfHashrateOverview shelfOverview = new ShelfHashrateOverview();
			shelfOverview.setYear(year);
			shelfOverview.setDetectTime(detectTime);
			shelfOverview.setMinerShelfId(minerShelfId);
			shelfOverview.setMinerShelfName(minerShelfName);
			shelfOverview.setNumAll(shelfNumAll);
			shelfOverview.setNumDetail(shelfNumDetail);
			shelfOverview.setNumFailure(shelfNumFailure);
			shelfOverview.setNumPassed(shelfNumPassed);
			shelfOverview.setNumUnpassed(shelfNumUnpassed);
			shelfOverview.setOverallTheory(shelfOverallTheo);
			shelfOverview.setOverallReal(shelfOverallReal);
			shelfOverview.setRatePassed(shelfRatePassed);
			OverviewDataHelper.saveShelfHashrateOverview(shelfOverview);
			System.out.println(minerShelfName+"机架算力汇总信息存储完成");
			
			numPassed += shelfNumPassed;
			numUnpassed += shelfNumUnpassed;
			overallTheory += shelfOverallTheo;
			overallReal += shelfOverallReal;
		}
		
		if(numDetail == 0){
			ratePassed = 0;
		}else{
			ratePassed = new BigDecimal((double) numPassed / (double) numDetail).setScale(4, RoundingMode.HALF_UP).doubleValue();
		}
		
		MineHashrateOverview mineOverview = new MineHashrateOverview();
		mineOverview.setNumAll(numAll);
		mineOverview.setNumDetect(numDetect);
		mineOverview.setNumDetail(numDetail);
		mineOverview.setNumFailure(numFailure);
		mineOverview.setNumPassed(numPassed);
		mineOverview.setNumUnpassed(numUnpassed);
		mineOverview.setRatePassed(ratePassed);
		mineOverview.setOverallTheory(overallTheory);
		mineOverview.setOverallReal(overallReal);
		mineOverview.setDetectTime(detectTime);
		OverviewDataHelper.saveMineHashrateOverview(mineOverview);
		System.out.println("矿场算力汇总信息存储完成");
	}
}
